/* -*- Mode: C; tab-width: 4;  c-basic-offset: 4                 -*- */
/*
 * transfer-view.c : A GtkTreeView that displays the file tranfer status.
 * Copyright (C) 2009 Lingtao Pan
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, 
 * Boston, MA 02111-1307, USA.
 */

#include "common.h"



static const char *dl_action[] = { "",   "Overwrite",  "Resume",  "Skip" };


static GtkTreeStore *create_download_model (void);
static gboolean on_dltreeview_button_click (GtkWidget *widget, 
                                GdkEventButton *event, gpointer data);
static void progress_renderer_func (GtkTreeViewColumn *col,
                                GtkCellRenderer *renderer, GtkTreeModel *model,
                                GtkTreeIter *iter, gpointer user_data);
static void rate_renderer_func (GtkTreeViewColumn *col,
                                GtkCellRenderer *renderer, GtkTreeModel *model,
                                GtkTreeIter *iter, gpointer user_data);
static void transfer_view_on_init (GftpInterface *gftp_interface);

static void transfer_view_update_state ();
static gboolean transfer_view_popup_menu_cb (GtkWidget *widget, gpointer data);

static void add_button (GtkWidget **widget, GtkBox *box, const gchar *stock)
{
    GtkWidget *image;

    image = gtk_image_new_from_stock (stock, GTK_ICON_SIZE_SMALL_TOOLBAR);
    *widget = gtk_button_new ();
    gtk_button_set_image (GTK_BUTTON (*widget), image);
    gtk_button_set_relief (GTK_BUTTON (*widget), GTK_RELIEF_NONE);
    gtk_box_pack_start (box, *widget, FALSE, FALSE, 0);  
}


void
transfer_view_setup (GftpInterface *gftp_interface)
{
    GtkTreeView *tv;
    GtkTreeStore *model;
    GtkCellRenderer *renderer;
    GtkTreeViewColumn *column;
    GtkWidget *tempwid, *hbox, *vbox;

    hbox = gtk_hbox_new (FALSE, 0);
    gftp_interface->dlbox = hbox;

    vbox = gtk_vbox_new (FALSE, 0);
    gtk_box_pack_end (GTK_BOX (hbox), vbox, FALSE, FALSE, 0);

    /* a dummy label */
    /* tempwid = gtk_label_new (""); */
    /* gtk_box_pack_start (GTK_BOX(vbox), tempwid, TRUE, TRUE, 0); */
    /* add_button (&gftp_interface->dlup_button, GTK_BOX(vbox), GTK_STOCK_GO_UP); */
    /* add_button (&gftp_interface->dldown_button, GTK_BOX(vbox), GTK_STOCK_GO_DOWN); */

    
    tempwid = gtk_scrolled_window_new (NULL, NULL);
    gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (tempwid),
                                    GTK_POLICY_AUTOMATIC,
                                    GTK_POLICY_AUTOMATIC);
    
    gftp_interface->dltreeview = gtk_tree_view_new ();

    gtk_container_add (GTK_CONTAINER (tempwid), gftp_interface->dltreeview);
    gtk_box_pack_start (GTK_BOX (hbox), tempwid, TRUE, TRUE, 0);

    model = create_download_model ();
    gftp_interface->dlstore = model;

    tv = GTK_TREE_VIEW (gftp_interface->dltreeview);
    gtk_tree_view_set_model (tv, GTK_TREE_MODEL (model));
  
    /* column 1, filename */
    renderer = gtk_cell_renderer_text_new ();
    column = gtk_tree_view_column_new_with_attributes (_("Filename"), 
                                     renderer, "text", COLUMN_DL_FILENAME, NULL);
    gtk_tree_view_column_set_resizable (column, TRUE);
    gtk_tree_view_column_set_max_width (column, 600);
    gtk_tree_view_column_set_min_width (column, 300);
    g_object_set (renderer, "ellipsize", PANGO_ELLIPSIZE_START,
                  "ellipsize-set", TRUE, NULL);

    gtk_tree_view_append_column (tv, column);

    /* column 2, action */
    renderer = gtk_cell_renderer_text_new ();
    column = gtk_tree_view_column_new_with_attributes (_("Action"), 
                                     renderer, "text", COLUMN_DL_ACTION, NULL);
    gtk_tree_view_append_column (tv, column);

    /* column 3, progress */
    column = gtk_tree_view_column_new ();
    gtk_tree_view_column_set_title (column, _("Progress"));
    gtk_tree_view_append_column (tv, column);

    renderer = gtk_cell_renderer_progress_new ();
    gtk_tree_view_column_pack_start (column, renderer, TRUE);
    gtk_tree_view_column_set_cell_data_func (column, renderer,
                                             progress_renderer_func,
                                             NULL, NULL);
  
    renderer = gtk_cell_renderer_text_new ();
    gtk_tree_view_column_pack_start (column, renderer, TRUE);  
    gtk_tree_view_column_add_attribute (column, renderer,
                                        "text", COLUMN_DL_PROGRESS_TEXT);

    /* column 4, rate */
    column = gtk_tree_view_column_new ();
    gtk_tree_view_column_set_title (column, _("Rate(KB/s)"));
    gtk_tree_view_append_column (tv, column);

    renderer = gtk_cell_renderer_text_new ();
    gtk_tree_view_column_pack_start (column, renderer, TRUE);
    gtk_tree_view_column_set_cell_data_func (column, renderer,
                                             rate_renderer_func,
                                             NULL, NULL);


    /* dummy column */
    renderer = gtk_cell_renderer_text_new ();
    column = gtk_tree_view_column_new_with_attributes ("", 
                                                       renderer, NULL);
    gtk_tree_view_append_column (tv, column);

    
    g_signal_connect (gftp_interface->dltreeview, "button_press_event",
                      G_CALLBACK(on_dltreeview_button_click), NULL);

    g_signal_connect (gftp_interface->dltreeview, "popup-menu",
                        G_CALLBACK (transfer_view_popup_menu_cb), NULL);

    transfer_view_on_init (gftp_interface);
}


static GtkTreeStore *
create_download_model (void)
{
  GtkTreeStore *store;

  store = gtk_tree_store_new (COLUMNS_DL, G_TYPE_STRING, G_TYPE_STRING, 
                              G_TYPE_INT, G_TYPE_STRING,
                              G_TYPE_INT, G_TYPE_DOUBLE, G_TYPE_POINTER);
  return store;
}





static void
progress_renderer_func (GtkTreeViewColumn *col,
                        GtkCellRenderer *renderer, GtkTreeModel *model,
                        GtkTreeIter *iter, gpointer user_data)
{
    gint progress, type;

    gtk_tree_model_get (model, iter, COLUMN_DL_TYPE, &type, 
                        COLUMN_DL_PROGRESS, &progress, -1);

    if (type == 0) {
        /* parent column */
        g_object_set (renderer, "visible", FALSE, NULL);
    } else {
        g_object_set (renderer, "visible", TRUE, "value", progress, NULL);
    }
}

static void
rate_renderer_func (GtkTreeViewColumn *col,
                        GtkCellRenderer *renderer, GtkTreeModel *model,
                        GtkTreeIter *iter, gpointer user_data)
{
    gdouble value;
    gint type;
    gchar *text;

    gtk_tree_model_get (model, iter, COLUMN_DL_TYPE, &type, 
                        COLUMN_DL_RATE, &value, -1);

    if (type == 0) {
    /* parent column */
        g_object_set (renderer, "visible", FALSE, NULL);
    } else {
        text = g_strdup_printf ("%.1f", value);
        
        g_object_set (renderer, "visible", TRUE, "text", text, NULL);
        g_free (text);
    }
}



/* ----------------- update related -------------------  */



static void
update_dlentry_progress (gftp_file *fle, int pcent, gchar *pro_str, gdouble rate);


/**
 * transfer_view_update_download_status:
 * @data: not used.
 *
 * A timeout callback of main loop, which updates the transfer view.
 **/
gint
transfer_view_update_download_status (gpointer data)
{
    gftp_file *fle;
    unsigned long remaining_secs;
    int rem_secs, rem_mins, rem_hours;
    static struct timeval last_tv = { 0, 0 };
    struct timeval cur_tv;
    double difftime;
    double kbs;
    gchar *pro_str;
    int pcent;
    guint status_id;

    gdk_threads_enter ();

    if (gftp_file_transfer_logs != NULL)
        display_cached_logs ();

    if (last_tv.tv_sec == 0) {
        gettimeofday (&last_tv, NULL);
    }

    gettimeofday (&cur_tv, NULL);
    memcpy (&last_tv, &cur_tv, sizeof (last_tv));
    difftime = (cur_tv.tv_sec - last_tv.tv_sec) + 
        ((double) (cur_tv.tv_usec - last_tv.tv_usec) / 1000000.0);
  
    if (transfer != NULL && transfer->started && !transfer->done) {
        g_static_mutex_lock (&transfer->statmutex);

        if (difftime <= 0)
            kbs = transfer->accum_bytes / 1024.0;
        else
            kbs = transfer->accum_bytes / 1024.0 / difftime;

        if (transfer->average_kbs == 0)
            transfer->average_kbs = kbs;
        else
            transfer->average_kbs = 0.2 * kbs + 0.8 * transfer->average_kbs;

        transfer->accum_bytes = 0;
    
        fle = transfer->curfle->data;
        if (S_ISDIR (fle->st_mode)) {
            g_static_mutex_unlock (&transfer->statmutex);
            gdk_threads_leave ();
            return TRUE;
        }

        pcent = (int) ( ((double) transfer->curtrans + transfer->curresumed)  
                        / (transfer->curfsize) * 100);
        if (pcent < 0)
            pcent = 0;
        if (pcent > 100)
            pcent = 100;

        if (transfer->curfsize < 1024) {
            pro_str =  g_strdup_printf ("%d B of %d B", 
                            (int) (transfer->curtrans + transfer->curresumed), 
                            (int) transfer->curfsize);
        } else if (transfer->curfsize < 1024 * 1024) {
            pro_str = g_strdup_printf ("%0.1f KB of %0.1f KB", 
                     (transfer->curtrans + transfer->curresumed)/1024.0,
                     transfer->curfsize/1024.0);
      
        } else {
            pro_str = g_strdup_printf ("%0.1f MB of %0.1f MB", 
                     (transfer->curtrans + transfer->curresumed)/(1024.0*1024.0),
                     transfer->curfsize/(1024.0*1024.0));
        }

        if (transfer->average_kbs == 0)
            remaining_secs = 0;
        else {
            remaining_secs = (unsigned long) ( ((double) (transfer->total_bytes - 
                                               transfer->trans_bytes -
                                               transfer->resumed_bytes)) 
                                          / (transfer->average_kbs * 1024.0) );
        }        

		/* release the lock */
        g_static_mutex_unlock (&transfer->statmutex);

        rem_secs = remaining_secs % 60;
        remaining_secs /= 60;
        rem_mins = remaining_secs % 60;
        remaining_secs /= 60;
        rem_hours = remaining_secs;

        update_dlentry_progress (fle, pcent, pro_str, kbs);
        g_free (pro_str);

        pro_str = g_strdup_printf ("Average download rate: %.1f KB/s; "
                                   "Remaining time: %d:%02d:%02d",
                                   transfer->average_kbs, rem_hours, rem_mins,
                                   rem_secs);
        status_id = gtk_statusbar_get_context_id (gftp_interface->dlstatus,
                                               "DownloadRate");
		
        gtk_statusbar_pop (gftp_interface->dlstatus, status_id);
        gtk_statusbar_push (gftp_interface->dlstatus, status_id, pro_str);
        g_free (pro_str);
    }

    gdk_threads_leave ();
  
    return TRUE;
}


static void
update_dlentry_progress (gftp_file *fle, int pcent, gchar *pro_str, gdouble rate)
{
  GtkTreePath *path;
  GtkTreeStore *store;
  GtkTreeIter iter;
  gtkui_file_pdata *uidata;
  
  uidata = fle->user_data;


  path = gtk_tree_row_reference_get_path (uidata->rowref);
  assert (path != NULL);
  store = GTK_TREE_STORE (gftp_interface->dlstore);
  gtk_tree_model_get_iter (GTK_TREE_MODEL (store), &iter, path);
  gtk_tree_store_set (store, &iter, COLUMN_DL_PROGRESS, pcent, 
                      COLUMN_DL_PROGRESS_TEXT, pro_str, 
                      COLUMN_DL_RATE, rate, -1);
  
}

void
transfer_view_update_item_upon_finish (gftp_file *fle)
{
    GtkTreePath *path;
    GtkTreeStore *store;
    GtkTreeIter iter;
    gtkui_file_pdata *uidata;
    char pro_str[30];

    uidata = fle->user_data;

    gdk_threads_enter (); 
  
    path = gtk_tree_row_reference_get_path (uidata->rowref);
    assert (path != NULL);
    store = GTK_TREE_STORE (gftp_interface->dlstore);
    gtk_tree_model_get_iter (GTK_TREE_MODEL (store), &iter, path);

    if (transfer->curfsize < 1024) {
        snprintf (pro_str, sizeof(pro_str), "%d B of %d B", 
                  (int)transfer->curfsize, (int)transfer->curfsize);
    } else if (transfer->curfsize < 1024 * 1024) {
        snprintf (pro_str, sizeof(pro_str), "%0.1f KB of %0.1f KB", 
                  transfer->curfsize/1024.0,
                  transfer->curfsize/1024.0);
      
    } else {
        snprintf (pro_str, sizeof(pro_str), "%0.1f MB of %0.1f MB", 
                  transfer->curfsize/(1024.0*1024.0),
                  transfer->curfsize/(1024.0*1024.0));
    }

    gtk_tree_store_set (store, &iter, COLUMN_DL_PROGRESS, 100, 
                        COLUMN_DL_PROGRESS_TEXT, pro_str, -1);

  
    gdk_threads_leave ();
}

static gchar* file_size_string (gftp_file *fle)
{
    gchar *str;
    if (fle->size < 1024) {
      str =  g_strdup_printf ("%d B of %d B", 
                  (int) fle->startsize, 
                  (int) fle->size);
    } else if (fle->size < 1024 * 1024) {
      str = g_strdup_printf ("%0.1f KB of %0.1f KB", 
                             fle->startsize/1024.0,
                             fle->size/1024.0);
      
    } else {
      str = g_strdup_printf ("%0.1f MB of %0.1f MB", 
                       fle->startsize/(1024.0*1024.0),
                       fle->size/(1024.0*1024.0));
    }

    return str;
}

void
transfer_view_update ()
{
    GtkTreeStore *store = GTK_TREE_STORE (gftp_interface->dlstore);
    GtkTreeIter parent, child;
    GList *iter;
    gftp_file *fle;
    struct gtkui_file_pdata *uidata;
    gchar *server;
    GtkTreePath *path;
    GtkTreeRowReference *rowref;
    gchar *tempstr;

    if (transfer == NULL)
        return;
  
    gtk_tree_store_clear (store);

    gtk_tree_store_append (store, &parent, NULL);

    if (transfer->fromreq != left_viewer->request) {
        server = g_strdup_printf ("From %s", transfer->fromreq->hostname);
    } else {
        server = g_strdup_printf ("To %s", transfer->toreq->hostname);
    }

    gtk_tree_store_set (store, &parent, COLUMN_DL_FILENAME, server, 
                        COLUMN_DL_ACTION, "", COLUMN_DL_PROGRESS, 0, 
                        COLUMN_DL_PROGRESS_TEXT, "",
                        COLUMN_DL_TYPE, 0, 
                        COLUMN_DL_ENTRY, (gpointer) transfer, 
                        -1);
    g_free (server);
  
    for (iter=transfer->files; iter; iter=iter->next) {
        fle = iter->data;

        if (S_ISDIR (fle->st_mode)) /* don't add folders */
            continue;
    
        tempstr = file_size_string (fle);

        gtk_tree_store_append (store, &child, &parent);
        gtk_tree_store_set (store, &child, COLUMN_DL_FILENAME, fle->file,
                            COLUMN_DL_ACTION, dl_action[(int)fle->transfer_action],
                            COLUMN_DL_PROGRESS, 0,
                            COLUMN_DL_PROGRESS_TEXT, tempstr,
                            COLUMN_DL_TYPE, 1,
                            COLUMN_DL_ENTRY, (gpointer)fle,
                            -1);
        g_free (tempstr);

        path = gtk_tree_model_get_path (GTK_TREE_MODEL (store), &child);
        rowref = gtk_tree_row_reference_new (GTK_TREE_MODEL (store), path);

        gtk_tree_path_free(path);

        uidata = alloc_file_pdata (fle);
        uidata->rowref = rowref;
    }

    gtk_tree_view_expand_all (GTK_TREE_VIEW (gftp_interface->dltreeview));
}


/* callbacks */

static void
do_popup_menu (GtkWidget *my_widget, GdkEventButton *event)
{
    GtkWidget *popup;
    int button, event_time;
    
    if (event != NULL) {
        button = event->button;
        event_time = event->time;
    } else {
        button = 0;
        event_time = gtk_get_current_event_time ();
    }

    popup = gtk_ui_manager_get_widget (ui_manager, "/TransferViewPopup");
    g_assert (popup != NULL);
    gtk_menu_popup (GTK_MENU (popup), NULL, NULL, NULL, NULL,
                    button, event_time);
}

static gboolean
on_dltreeview_button_click (GtkWidget *widget, GdkEventButton *event, 
                            gpointer data)
{
    if ((event->button == 3 ) && (event->type == GDK_BUTTON_PRESS)) {
        do_popup_menu (widget, event);
        return TRUE;
    }
    
    return FALSE;         
}

static gboolean
transfer_view_popup_menu_cb (GtkWidget *widget, gpointer data)
{
    do_popup_menu (widget, NULL);
    return TRUE;
}

void transfer_resume_cb (GtkMenuItem *item, gpointer data)
{
    transfer_view_on_transfer_started ();
    gftpui_generic_thread ((thread_func) transfer_resume, NULL);
    transfer_view_on_transfer_stopped ();
}


void transfer_stop_cb (GtkMenuItem *item, gpointer data)
{
  g_static_mutex_lock (&transfer->structmutex);
  if (gftp_transfer_is_active (transfer)) {  
    transfer->cancel = 1;
    g_static_mutex_unlock (&transfer->structmutex);
    return;
  }
  g_static_mutex_unlock (&transfer->structmutex);


  if (right_viewer->request->running) {
    pthread_kill (right_viewer->tid, SIGINT);
    
    if (right_viewer->request->wakeup_main_thread[1] > 0)
      write (right_viewer->request->wakeup_main_thread[1], " ", 1);
  }
}


void transfer_clean_all_cb      (GtkMenuItem *item, gpointer data)
{
    GtkTreeStore *store = gftp_interface->dlstore;

    gtk_tree_store_clear (store);

    gftp_transfer_destroy (transfer);

    transfer = NULL;
}

void transfer_item_move_up_cb   (GtkMenuItem *item, gpointer data)
{
    GtkTreeStore *store = gftp_interface->dlstore;
    GtkTreeSelection *selection;
    GList *slist;
    GtkTreePath *path;
    GtkTreeIter iter, prev;
    gftp_file *fle, *prevfle;
    int depth;

    selection = gtk_tree_view_get_selection 
                   (GTK_TREE_VIEW(gftp_interface->dltreeview));
    if (selection == NULL)
        return;

    slist = gtk_tree_selection_get_selected_rows (selection, 
                                      (GtkTreeModel **)&store);

    if (g_list_length (slist) > 1) 
        goto out;

    path = (GtkTreePath *) slist->data;
    
    if (gtk_tree_model_get_iter (GTK_TREE_MODEL (store),
                                 &iter, path)) 
    {
        depth = gtk_tree_path_get_depth (path);
        if (depth == 2) {
            if (gtk_tree_path_prev (path)) {
                gtk_tree_model_get_iter (GTK_TREE_MODEL (store),
                                         &prev, path);
                
                gtk_tree_model_get (GTK_TREE_MODEL (store), &iter, 
                                    COLUMN_DL_ENTRY, &fle, -1);

                gtk_tree_model_get (GTK_TREE_MODEL (store), &prev, 
                                    COLUMN_DL_ENTRY, &prevfle, -1);

                /* don't move a file before finished files */
                if (prevfle->transfer_done)
                    goto out;

                gftp_transfer_exchange_file_pos (transfer, fle, prevfle);
                
                gtk_tree_store_move_before (store, &iter, &prev);
            }
        }
    }
   
out:
    g_list_foreach (slist, (GFunc)gtk_tree_path_free, NULL);
    g_list_free (slist);
}

void transfer_item_move_down_cb (GtkMenuItem *item, gpointer data)
{
    GtkTreeStore *store = gftp_interface->dlstore;
    GtkTreeSelection *selection;
    GList *slist;
    GtkTreePath *path;
    GtkTreeIter iter, next;
    gftp_file *fle, *nextfle;
    int depth;

    selection = gtk_tree_view_get_selection 
                   (GTK_TREE_VIEW(gftp_interface->dltreeview));
    if (selection == NULL)
        return;

    slist = gtk_tree_selection_get_selected_rows (selection, 
                                      (GtkTreeModel **)&store);


    if (g_list_length (slist) > 1)  /* user selected multiple columns  */
        goto out;

    path = (GtkTreePath *) slist->data;
    
    if (gtk_tree_model_get_iter (GTK_TREE_MODEL (store),
                                 &iter, path)) 
    {
        depth = gtk_tree_path_get_depth (path);
        if (depth == 2) {
            gtk_tree_path_next (path);
            if (gtk_tree_model_get_iter (GTK_TREE_MODEL (store),
                             &next, path) == FALSE)
                goto out;
                
            gtk_tree_model_get (GTK_TREE_MODEL (store), &iter, 
                                COLUMN_DL_ENTRY, &fle, -1);

            /* don't move a finished file */
            if (fle->transfer_done)
                goto out;

            gtk_tree_model_get (GTK_TREE_MODEL (store), &next, 
                                COLUMN_DL_ENTRY, &nextfle, -1);


            gftp_transfer_exchange_file_pos (transfer, fle, nextfle);
                
            gtk_tree_store_move_after (store, &iter, &next);

        }
    }
   
out:
    g_list_foreach (slist, (GFunc)gtk_tree_path_free, NULL);
    g_list_free (slist);
}

void transfer_item_delete_cb    (GtkMenuItem *item, gpointer data)
{
    GtkTreeSelection *selection;
    GList *slist, *ptr;
    GtkTreeStore *store = gftp_interface->dlstore;

    selection = gtk_tree_view_get_selection 
                   (GTK_TREE_VIEW(gftp_interface->dltreeview));
    if (selection == NULL)
        return;

    slist = gtk_tree_selection_get_selected_rows (selection, 
                                      (GtkTreeModel **)&store);

    for (ptr=slist; ptr; ptr=ptr->next) {
        GtkTreePath *path = (GtkTreePath *)ptr->data;
        int depth = gtk_tree_path_get_depth (path);
        GtkTreeIter iter;
        gftp_file *fle;

        if (gtk_tree_model_get_iter (GTK_TREE_MODEL (store),
                                     &iter, path)) 
        {
            if (depth == 2) {
                gtk_tree_model_get (GTK_TREE_MODEL (store), &iter, 
                                    COLUMN_DL_ENTRY, &fle, -1);
                gftp_transfer_remove_file (transfer, fle);
                gtk_tree_store_remove (store, &iter);
                g_free (fle);
            }
        }
    }

    transfer_view_update_state ();

    g_list_foreach (slist, (GFunc)gtk_tree_path_free, NULL);
    g_list_free (slist);

}




/* ------------------ state transition functions ------------------ */

static void transfer_view_on_init (GftpInterface *interface)
{
    GtkActionGroup *group = interface->transfer_action_group;
        
    gtk_action_group_set_sensitive (group, FALSE);
}


static void set_action (GtkActionGroup *group, gchar *name, gboolean value)
{
    GtkAction *action;

    action = gtk_action_group_get_action (group, name);
    gtk_action_set_sensitive (action, value);
}


void transfer_view_on_transfer_started ()
{
    GtkActionGroup *group = gftp_interface->transfer_action_group;

    gtk_action_group_set_sensitive (group, TRUE);

    set_action (group, "TransferStop", TRUE);
    set_action (group, "TransferResume", FALSE);
    set_action (group, "TransferCleanAll", FALSE);
    set_action (group, "TransferItemMoveUp", FALSE);
    set_action (group, "TransferItemMoveDown", FALSE);
    set_action (group, "TransferItemDelete", FALSE);

    /* gftp_viewer_navigation_disable (left_viewer); */
    gftp_viewer_navigation_disable (right_viewer);
    gftp_viewer_navigation_disable (left_viewer);
}

void transfer_view_on_transfer_stopped ()
{
    int state;
    GtkActionGroup *group = gftp_interface->transfer_action_group;

    gtk_action_group_set_sensitive (group, TRUE);

    set_action (group, "TransferStop", FALSE);

    set_action (group, "TransferCleanAll", TRUE);

    state = transfer_get_state ();
    if (state == TRANSFER_STOPPED) {
        set_action (group, "TransferResume", TRUE);
        set_action (group, "TransferItemMoveUp", TRUE);
        set_action (group, "TransferItemMoveDown", TRUE);
        set_action (group, "TransferItemDelete", TRUE);
    } else {
        set_action (group, "TransferResume", FALSE);
        set_action (group, "TransferItemMoveUp", FALSE);
        set_action (group, "TransferItemMoveDown", FALSE);
        set_action (group, "TransferItemDelete", FALSE);
    }

    gftp_viewer_navigation_enable (right_viewer);
    gftp_viewer_navigation_enable (left_viewer);
}


static void transfer_view_update_state ()
{
    
}


